#include "device.h"
#include "component.h"

/* 调试打印接口 */
#define EXTEND_KDS_LOG(format, ...)  __OSAL_LOG("[mc60_uart.c] " C_YELLOW format C_NONE, ##__VA_ARGS__)


/* 定义虚拟硬件接口 */
#ifdef EXTEND_ITIC
#define EXTEND_KDS_VHWL				vUART_12 //
#endif

#define EXTEND_INT_VHWL				vPIN_C46
#define BLEWAKEMCU_VHWL	            vPIN_I22

/* UART事件处理周期 */
#define EXTEND_KDS_EVT_PROC_CYCLE	(10)

/* UART事件 */
#define EVENT_EXTEND_KDS			(1 << 0)
#define EVENT_EXTEND_KDS_SEND_ACK   (1 << 1)

/* EXTEND_KDS环形接收缓存 */
#ifndef EXTEND_KDS_RB_RXBUF_LENGTH
#define EXTEND_KDS_RB_RXBUF_LENGTH 	(128)			   	//EXTEND_KDS 接收环形缓存长度
#endif

///////////// 定义协议解析层数据结构 /////////////////////////////////////////////////////////////////////////////////////////
#define PROTOCOL_CMD_PACKET_STX      0X5A   //0XF5  命令包数据头
#define PROTOCOL_ACK_PACKET_STX      0X5A   //0X5F  应答包数据头
#define PROTOCOL_CMD_PACKET_END      0XA5   //命令包数据尾

#define PACK_TYPE_ACK                0X01   //应答包类型：应答包
//---------------------------------------------------------------------------

#define PROTOCOL_SEND_TIMES          3      //锁发送命令包的最大次数
#define PROTOCOL_RESEND_CMD_TIMEOUT  1000   //200   锁重发命令包间隔时间ms
#define PROTOCOL_SEND_ACK_TIME_GAP   20     //锁发出多包ACK的间隔时间ms

#define PROTOCOL_RX_CMD_BUF_QTY      10     //接收的命令包缓存数量（最多连续接收10个命令包）//--------------


#define UART_TASK_QUEUE_LEN     	 10		//定义发送命令的最大数目
///////////// 串口通信协议：数据包结构 /////////////////////////////////////////////////////////////////////////////////////////
#pragma pack(1)
/* 协议头结构 */
typedef struct //<------------------------
{
	uint8_t stx;  //数据头
	uint16_t cmd; //命令字
	uint8_t reserved;//预留字节,默认用0xFF
	uint8_t len;  //数据长度
}ProtocolDataHead_stu_t;

/* 数据包结构 */
typedef struct
{
	ProtocolDataHead_stu_t head;
	uint8_t dataBuf[];//数据 + 校验和 + 数据尾
	//uint16_t sum; //校验和
	//uint8_t end;  //数据尾
}ProtocolPacket_stu_t;


// /* 应答包结构 */
// typedef struct
// {
// 	ProtocolDataHead_stu_t head;
// 	uint8_t cmd;
// 	uint8_t ret;
// 	uint8_t dataBuf[];//数据域长度不定
// }AckPacket_stu_t;
#pragma pack()
//<------------------------------
//tx命令包结构
typedef struct 
{
	uint8_t  buffer[MAX_PACKAGE_LEN]; //发送缓存
	uint16_t  len;                     //数据长度
	uint32_t acktimeout;              //等待ACK的超时时间（为0：不需要ACK）
    mc60_send_cb_fun_t cb;            //发送命令回调（为NULL：不需要回调）  extkds_send_cb_fun_t
}uart_txcmd_packet_stu_t; //ok 

/* 命令包发送状态信息 */
static struct
{
    uart_txcmd_packet_stu_t data;     //数据
	uint32_t timeStamp;               //最后一次发送的时间戳
	uint8_t  cnt;                     //发送次数（可能重发）
	enum
	{                                 //当前发送的状态
		TX_STA_IDLE,                  //空闲
		TX_STA_WAIT_ACK,              //等待模块回复应答包
	}status;
	RingBufferHandle_t tbHandle;
}CmdPacketTxInfo;//ok 

/* 命令包接收状态信息：记录蓝牙和Uart两个设备的发送状态 */
static struct
{
	uint8_t protocolBuf[MAX_PACKAGE_LEN];//协议解析缓存
	uint8_t protocolCount;               //协议解析计数变量
	RingBufferHandle_t rbHandle;
	Mc60UartMsg_t *rx_msg;
	enum
	{ 
        RX_STA_IDLE,                        //空闲
        RX_STA_SEND_ACK,                    //正在发送多包ACK
    }status;
}CmdPacketRxInfo; //ok 

/* 定义发送缓存 */
static uint8_t uart_tx_buffer[MAX_PACKAGE_LEN] = {0};
static uint16_t tx_ctrl_flg=0; 
// static uint16_t g_special_len = 0; //兼容0xDE指令，同一用这个变量做长度 //

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
  * @brief  打印HEX数据，最多只能打印32字节
  * @note
  *
  * @param  pData：数据指针
  * @param  len：数据长度
  */
static void ExtKds_PrintfHexData(char *Msg,uint8_t *pData, uint16_t len) //ok 
{
	char *str_buffer = OSAL_Malloc(len * 3 + 1);
    if (str_buffer != NULL)
    {
        memset(str_buffer,0,len * 3 + 1);
        EXTEND_KDS_LOG("%s:%d(Bytes)\r\n", Msg, len);
        if (str_buffer != NULL)
        {
            for (int i=0; i<len; i++)
            {
                sprintf(&str_buffer[i*3], "%02X ", pData[i]);
            }
            EXTEND_KDS_LOG("%s\r\n\r\n", str_buffer);
        }
    }
	if (str_buffer) OSAL_Free(str_buffer);
}

/**
  * @brief  计算校验和
  * @note
  *
  * @param  pData：数据指针
  * @param  len：数据长度
  * @return 成功返回校验和
  */
static uint16_t ExtKds_CalcCheckSum(uint8_t *pData, uint16_t len) //ok 
{
	uint16_t sum = 0;

	for (; len; len--)
	{
		sum += *pData++;
		
	}
	return sum;
}

/**
  * @brief  获取发送缓存区的状态
  * @note
  *
  * @return 缓存区为空返回0
  */
static uint8_t ExtKds_GetTxBufferStatus(void) //ok
{
	return tx_ctrl_flg;
}

/**
  * @brief  加载待发送的数据
  * @note   将要发出的数据，填入发送缓存区
  *
  * @param  pData：数据指针
  * @param  len：数据长度
  * @return 成功返回SUCCESS，失败返回ERROR
  */
static ErrorStatus ExtKds_LoadingDataToBeSent(uint8_t *pData, uint16_t len) //ok 
{
	uint8_t *pSendBuf = uart_tx_buffer;
	EXTEND_KDS_LOG("uart_tx_buffer[0]:%02X\r\n",pSendBuf[0]);
	if (tx_ctrl_flg == 0)
	{
		tx_ctrl_flg = len;
		memcpy(pSendBuf, pData, len);
		return SUCCESS;
	}
	EXTEND_KDS_LOG("Loading Tx data failed\r\n");
	return ERROR;
}

/**
  * @brief  处理发送缓存
  * @note   将发送缓存区的数据，通过串口发出，并处理Int控制逻辑
  *
  */
static void ExtKds_ProcessTxBuffer(void)
{
	static uint32_t timestamp=0;
    uint32_t currentTime = 0;
	uint8_t *pSendBuf = uart_tx_buffer;

	if (tx_ctrl_flg > 0)
	{	
		if (tx_ctrl_flg & 0X8000)
		{
			EXTEND_KDS_LOG("EXTEND_INT 003\n");
			/* 调用硬件层write接口，发出数据 */
			ExtKds_PrintfHexData("Uart send packet",pSendBuf,  tx_ctrl_flg & 0X7FFF);
			Device_Write(EXTEND_KDS_VHWL, pSendBuf, tx_ctrl_flg & 0X7FFF, 0);
			// OSAL_UpdateSleepTime(2000, 1); //
			// Device_Write(EXTEND_INT_VHWL,NULL,0,0);
			
			timestamp = 0;
			tx_ctrl_flg = 0;
		}
		else
		{
			/* 开始发数据，通知底层先发出唤醒信号 */
			currentTime = OSAL_GetTickCount();
            if(timestamp == 0)
            {
                timestamp =  OSAL_GetTickCount();
				EXTEND_KDS_LOG("EXTEND_INT 001\n");
                Device_Write(EXTEND_INT_VHWL, NULL, 0, 1); 
            }
            else if (OSAL_PastTime(currentTime, timestamp)  > 120)//60
            {
                tx_ctrl_flg |= 0X8000;
				EXTEND_KDS_LOG("EXTEND_INT 002\n");
            }
			
		}
	}
}

/**
  * @brief  重发命令包，并处理超时逻辑
  *
  * @note   MCU发出命令包后，超时没有收到确认包，就重发
  */
static void ExtKds_ResendCmdPacket(void)
{
	uint8_t send_timeout_msg = 0;
	uint32_t currentTime = OSAL_GetTickCount();

	if (CmdPacketTxInfo.status == TX_STA_WAIT_ACK)//等待应答包
	{
       if (OSAL_PastTime(currentTime, CmdPacketTxInfo.timeStamp) > CmdPacketTxInfo.data.acktimeout)//ERR:等待应答包超时
		{
           EXTEND_KDS_LOG("wait ack timeout\r\n");
		   send_timeout_msg = 1;
		   CmdPacketTxInfo.status = TX_STA_IDLE;
		}
	}

	/* exec timeout callback */
   if(send_timeout_msg)
   {
    //    Mc60UartMsg_t *tmp = (Mc60UartMsg_t *)OSAL_Malloc(sizeof(Mc60UartMsg_t));
    //    if(tmp)
    //    {
    //        tmp->msgType = MC60_EXEC_CB;
    //        tmp->cb = CmdPacketTxInfo.data.cb;
    //        tmp->cmd = ((ProtocolPacket_stu_t *)CmdPacketTxInfo.data.buffer)->head.cmd; // CmdPacket_stu_t
    //        tmp->len = ((ProtocolPacket_stu_t *)CmdPacketTxInfo.data.buffer)->head.len;
	// 	   tmp->times = 0;
	// 	   memcpy(tmp->data, &((ProtocolPacket_stu_t *)CmdPacketTxInfo.data.buffer)->dataBuf, ((ProtocolPacket_stu_t *)CmdPacketTxInfo.data.buffer)->head.len + 3);

	// 	//    CmdPacketRxInfo.rx_msg->cmd = pCmdPacket->head.cmd;
	// 	//    CmdPacketRxInfo.rx_msg->len = pCmdPacket->head.len;//
	// 	//    CmdPacketRxInfo.rx_msg->times = 0;
	// 	//    memcpy(CmdPacketRxInfo.rx_msg->data, &pCmdPacket->dataBuf, CmdPacketRxInfo.rx_msg->len);

    //        OSAL_MessagePublish(tmp, sizeof(Mc60UartMsg_t) + tmp->len);
	// 	   OSAL_Free(tmp);
	// 	   EXTEND_KDS_LOG("ExtKds_ResendCmdPacket>>>\r\n");
    //    }
    //    CmdPacketTxInfo.data.cb = NULL;
   }
}


/**
  * @brief  处理接收的应答包
  * @note
  *
  * @param  pAckPacket：应答包数据指针
  */
// static void ExtKds_ProcessRxAckPacket(AckPacket_stu_t *pAckPacket) //不用管
// {
// 	if (CmdPacketTxInfo.status == TX_STA_WAIT_ACK && pAckPacket->cmd == CmdPacketTxInfo.data.buffer[sizeof(ProtocolDataHead_stu_t)])
// 	{
// 		if(pAckPacket->cmd == 0xB0)//配网指令
// 		{
// 			OSAL_SetTaskStatus(TASK_STA_NORMAL); //指纹流程开始：允许系统休眠
// 		}
// 		CmdPacketTxInfo.status = TX_STA_IDLE;
// 		Mc60UartMsg_t *tmp = (Mc60UartMsg_t *)OSAL_Malloc(sizeof(Mc60UartMsg_t) + g_special_len - 1);
// 		if(tmp)
// 		{
// 			tmp->msgType = MC60_EXEC_CB;
// 			tmp->cb = CmdPacketTxInfo.data.cb;
// 			tmp->cmd = ((CmdPacket_stu_t *)CmdPacketTxInfo.data.buffer)->cmd; //ProtocolPacket_stu_t
// 			tmp->len = g_special_len - 1;
// 			memcpy(&tmp->data, &pAckPacket->ret, tmp->len);
// 			OSAL_MessagePublish(tmp, sizeof(Mc60UartMsg_t) + tmp->len);
// 			OSAL_Free(tmp);
// 		}
// 	}
// }

static ErrorStatus ExtKds_SendAck(uint16_t cmd, void *data, uint16_t len)  //uint8_t
{
   uint16_t checksum_len = 0;
   uint16_t checksum = 0;
   ErrorStatus res = ERROR;
   ProtocolPacket_stu_t *sdata = (ProtocolPacket_stu_t *)OSAL_Malloc(sizeof(ProtocolPacket_stu_t) + len +3);
   sdata->head.stx = PROTOCOL_ACK_PACKET_STX;

	uint8_t data_crc[20]; // 
	// //升级赛普拉斯wifi锁，固定包1035个长度，这里用0表示
	// if ((0x92 == cmd) && (1040 == len))
	// {
	// 	sdata->head.len = 0;
	// 	checksum_len = len + 1;
	// }
	// else
	//{
		sdata->head.reserved = 0xFF;
		sdata->head.len = len;//- 3;        //(len + 1)&0XFF;
		checksum_len = sdata->head.len + 4;
	//}

   sdata->head.cmd = cmd;
   memcpy(sdata->dataBuf,data,len);//
   
   //EXTEND_KDS_LOG("checksum_len:%d\n",checksum_len);
   
   data_crc[0] = (uint8_t)(sdata->head.cmd & 0x00FF);
   data_crc[1] = (uint8_t)(sdata->head.cmd >> 8); //
   data_crc[2] = sdata->head.reserved;
   data_crc[3] = sdata->head.len;
   memcpy(&data_crc[4],sdata->dataBuf,len);

  // checksum = ExtKds_CalcCheckSum((uint8_t*)sdata->head.cmd, checksum_len);//sdata->head.cmd  (uint8_t*)data1

    checksum = ExtKds_CalcCheckSum(data_crc, checksum_len);
	//EXTEND_KDS_LOG("data_crc[0]:%02x,data_crc[1]:%02x \n",data_crc[0],data_crc[1]);
	//EXTEND_KDS_LOG("checksum:%04x",checksum);

    sdata->dataBuf[sdata->head.len] = (checksum  >> 8);
	sdata->dataBuf[sdata->head.len + 1] = (checksum & 0x00FF);
	sdata->dataBuf[sdata->head.len + 2] = PROTOCOL_CMD_PACKET_END;

	EXTEND_KDS_LOG("start send ack...\r\n");
	// OSAL_UpdateSleepTime(3000, 1);//---
	//EXTEND_KDS_LOG("ExtKds_SendAck cmd: %04x, len: %d\r\n", sdata->head.cmd, sdata->head.len);
	//ExtKds_PrintfHexData("ExtKds Send Ack",sdata->dataBuf, len);


//    if (sdata->dataBuf[0] == 0x00 || sdata->dataBuf[0] == 0x01)//需要在次发送ACK
//    {
//        //sdata->dataBuf[0] = 0x80;
// 		if (CmdPacketRxInfo.rx_msg) CmdPacketRxInfo.rx_msg->times++;
//        OSAL_EventSingleCreate(COMP_MC60_UART, EVENT_EXTEND_KDS_SEND_ACK, PROTOCOL_SEND_ACK_TIME_GAP, EVT_PRIORITY_MEDIUM);
//    }
//    else
   {
       if (CmdPacketRxInfo.rx_msg)
       {
           OSAL_Free(CmdPacketRxInfo.rx_msg);
           CmdPacketRxInfo.rx_msg = NULL;
       }  
       CmdPacketRxInfo.status = RX_STA_IDLE; 
   }

//    if(sdata->cmd == 0xDE)
// 	{
// 		sdata->dataBuf[1] = ((len + 1)>>8)&0XFF;
// 		sdata->head.sum = ExtKds_CalcCheckSum(&sdata->cmd,(len + 1));
// 	}
// 	else
//	{
		//checksum = ExtKds_CalcCheckSum(&sdata->cmd, checksum_len);
//	}

	if (Device_Write(EXTEND_KDS_VHWL, sdata, sizeof(ProtocolPacket_stu_t) + len + 3, 0) == 0)
	{
		res = SUCCESS;
		//ExtKds_PrintfHexData("ExtKds Send Ack",(uint8_t *)sdata,sizeof(ProtocolPacket_stu_t) + len +3);
	}
   if (sdata) OSAL_Free(sdata);
   return res;
}

/**
  * @brief  处理接收的命令包
  * @note
  *
  * @param  pCmdPacket：数据包指针
  */
static void ExtKds_ProcessRxCmdPacket(ProtocolPacket_stu_t *pCmdPacket) 
{
	uint8_t len = pCmdPacket->head.len;
	static uint8_t last_len = 0; //用来保存上一次的长度，比如收到0xB0没有进行ACK，下次收到更长的指令就内存溢出了
	//EXTEND_KDS_LOG("Recv packet, cmd: 0x%04X\r\n", pCmdPacket->head.cmd);
	ExtKds_PrintfHexData("rev data",(uint8_t *)pCmdPacket,len + 8);

	if (CmdPacketRxInfo.rx_msg == NULL) 
	{
		last_len = len;
		CmdPacketRxInfo.rx_msg = (Mc60UartMsg_t *)OSAL_Malloc(sizeof(Mc60UartMsg_t) + len);//多包ACK结束时需要释放
	}
	else
	{
		if(last_len < len) //上次申请的长度不够
		{
			EXTEND_KDS_LOG("last_len: %d, len: %d\r\n", last_len, len);
			last_len = len;
			OSAL_Free(CmdPacketRxInfo.rx_msg);
			CmdPacketRxInfo.rx_msg = (Mc60UartMsg_t *)OSAL_Malloc(sizeof(Mc60UartMsg_t) + len);
		}
	}
	
	if (CmdPacketRxInfo.rx_msg != NULL)
	{
		if (CmdPacketTxInfo.status == TX_STA_WAIT_ACK ) //
		{
			CmdPacketTxInfo.status = TX_STA_IDLE;
			//CmdPacketRxInfo.rx_msg->msgType = EXT_EXEC_CB_MI;//
            //CmdPacketRxInfo.rx_msg->cb = CmdPacketTxInfo.data.cb;//
			EXTEND_KDS_LOG("ExtKds_ProcessRxCmdPacket TX_STA_WAIT_ACK\r\n");
		}
		// else
		// {
		// 	CmdPacketRxInfo.rx_msg->msgType = MC60_RECV_CMD_PACKET;
		// }
		CmdPacketRxInfo.rx_msg->msgType = MC60_RECV_CMD_PACKET;//
		CmdPacketRxInfo.rx_msg->cmd = pCmdPacket->head.cmd;
		CmdPacketRxInfo.rx_msg->len = pCmdPacket->head.len;//
		CmdPacketRxInfo.rx_msg->times = 0;
		memcpy(CmdPacketRxInfo.rx_msg->data, &pCmdPacket->dataBuf, CmdPacketRxInfo.rx_msg->len);
//		EXTEND_KDS_LOG("publish data size=%d\r\n", sizeof(Mc60UartMsg_t) + CmdPacketRxInfo.rx_msg->len);

		
		//EXTEND_KDS_LOG("cmd:%04X\n",CmdPacketRxInfo.rx_msg->cmd);
		//EXTEND_KDS_LOG("len:%d\n",CmdPacketRxInfo.rx_msg->len);
//		ExtKds_PrintfHexData("OSAL_MessagePublish data",CmdPacketRxInfo.rx_msg->data,len);
//		ExtKds_PrintfHexData(">> OSAL_MessagePublish data",CmdPacketRxInfo.rx_msg->data,len + 8);//

		OSAL_MessagePublish(CmdPacketRxInfo.rx_msg, sizeof(Mc60UartMsg_t) + CmdPacketRxInfo.rx_msg->len);
		// if (0xB0 != CmdPacketRxInfo.rx_msg->cmd)
		// {
		// 	CmdPacketRxInfo.status = RX_STA_SEND_ACK;
		// }
	}
	else
	{
		EXTEND_KDS_LOG("err CmdPacketRxInfo.rx_msg = null\r\n");
		return;
	}
	
	/* 发出确认包 */
	//ExtKds_SendConfrimPacket(0x80);
}

/**
  * @brief  解析接收的数据包
  * @note
  *
  * @param  pData：数据包地址
  */
static void ExtKds_ParseRxPacket(uint8_t *pData)
{
	if (pData == NULL)
    {
		//EXTEND_KDS_LOG("ExtKds_ParseRxPacket pData = NULL\r\n");
        return;
    }

	ProtocolPacket_stu_t *pPacketData = (ProtocolPacket_stu_t *)pData; //ProtocolDataHead_stu_t

	if (pPacketData->head.stx == PROTOCOL_CMD_PACKET_STX)
	{
		/* 处理接收的命令包 */
		ExtKds_ProcessRxCmdPacket((ProtocolPacket_stu_t *)pPacketData);// CmdPacket_stu_t
	}
	//else
	// {
	// 	/* 处理接收应答包 */
	// 	ExtKds_ProcessRxAckPacket((AckPacket_stu_t *)pData);
	// }
}

/**
  * @brief  从底层环形缓存获取一包数据并解析
  *
  * @note   底层驱动收到数据，会暂存在环形缓存区
  *
  * @return 返回解析后的数据包地址，解析失败返回NULL
  */
static uint8_t *ExtKds_GetOnePacket(void)
{
	static uint8_t getPacketTimeoutCnt = 0;
	uint8_t tmpData = 0;
	uint16_t packetLen; 
	uint16_t protocol_sum;

	if (OSAL_RingBufferRead(CmdPacketRxInfo.rbHandle, &tmpData) == 0)
	{
		/* 连续3次没有读取到数据（30ms） */
		if (++getPacketTimeoutCnt >= 3)
		{
			getPacketTimeoutCnt = 0;
			CmdPacketRxInfo.protocolCount = 0;//清0解析计数
		}
		return NULL;
	}
	getPacketTimeoutCnt = 0;

	uint16_t *pCnt = (uint16_t *)&(CmdPacketRxInfo.protocolCount);  //解析计数
	uint8_t *protocolBuff = CmdPacketRxInfo.protocolBuf; 			//解析缓存
	do
	{
		if (*pCnt == 0)
		{
			if (tmpData == PROTOCOL_CMD_PACKET_STX)    //命令帧
			{
				protocolBuff[0] = tmpData;
				*pCnt = 1;
			}
		}
		else if (*pCnt > 0)     //包头通过后才开始解析数据  001:帧头
		{
			protocolBuff[*pCnt] = tmpData;
			*pCnt = *pCnt + 1;
			if (*pCnt > 5)
			{
				//ProtocolDataHead_stu_t *pPacketHead = (ProtocolDataHead_stu_t *)protocolBuff;
				ProtocolPacket_stu_t *pPacketHead = (ProtocolPacket_stu_t *)protocolBuff;
				packetLen = pPacketHead->head.len + 8;
					
				if (*pCnt >= MAX_PACKAGE_LEN || packetLen == *pCnt)
				{
					if (packetLen == *pCnt)
					{
						protocol_sum = (pPacketHead->dataBuf[pPacketHead->head.len] << 8) +  pPacketHead->dataBuf[pPacketHead->head.len + 1] ;
						if ( protocol_sum == ExtKds_CalcCheckSum(protocolBuff + 1, packetLen - 4) ) //002:校验 
						{     
							 if ( pPacketHead->dataBuf[pPacketHead->head.len + 2] == PROTOCOL_CMD_PACKET_END ) //003:数据尾
							 {
								//ExtKds_PrintfHexData("MC60 Uart Rx",protocolBuff, packetLen);
								*pCnt = 0;
								//g_special_len = packetLen - 4;
								return protocolBuff;//接收完成
							}
						}
						else
						{
							ExtKds_PrintfHexData("MC60 Uart Rx CRC ERR",protocolBuff, packetLen);
						}
					}
					*pCnt = 0;
					return NULL;
				}
			}
		}
	} while(OSAL_RingBufferRead(CmdPacketRxInfo.rbHandle, &tmpData));
	return NULL;
}

/**
  * @brief  Uart任务 通信协议处理
  *
  * @note   该函数会每间隔10ms执行一次
  */
static void ExtKds_ProtocolPro(void) //ok
{
    if (ExtKds_GetTxBufferStatus() != 0)
    {
        ExtKds_ProcessTxBuffer();      //处理发送缓存中的数据
    }
    else
    {
        ExtKds_ParseRxPacket( ExtKds_GetOnePacket() );//解析数据
        ExtKds_ResendCmdPacket();      //重发命令包-----
    }
}

/**
  * @brief  判断协议层是否为空闲状态
  * @note
  *
  * @return 空闲：返回SUCCESS， 正忙：返回ERROR
  */
static ErrorStatus ExtKds_IsProtocolIdle(void) //ok 
{
	/* 当前没有发出命令、发送缓存为空、接收的命令也处理完成了，才能发出新命令 */
	if ( CmdPacketTxInfo.status == TX_STA_IDLE && ExtKds_GetTxBufferStatus() == 0 && CmdPacketRxInfo.status == RX_STA_IDLE)
	{
		return SUCCESS;
	}
	return ERROR;
}

/**
  * @brief  Uart任务 协议层初始化
  *
  * @note
  */
static void ExtKds_ProtocolInit(void) //ok 
{
	CmdPacketTxInfo.status = TX_STA_IDLE;
	CmdPacketTxInfo.cnt = 0;
	CmdPacketRxInfo.status = RX_STA_IDLE;
	CmdPacketRxInfo.rx_msg = NULL;
	memset(CmdPacketRxInfo.protocolBuf, 0, sizeof(CmdPacketRxInfo.protocolBuf));
	CmdPacketRxInfo.protocolCount = 0;
}

//处理TX队列
static void ExtKds_ProcessTxQueue(void)//ok
{
    uart_txcmd_packet_stu_t txcmd_packet = {0};
    
    if (ExtKds_IsProtocolIdle() != SUCCESS)
    {
        return;
    }
	if (OSAL_RingBufferRead(CmdPacketTxInfo.tbHandle, &txcmd_packet) != SUCCESS)
	{
		return;
	}
    CmdPacketTxInfo.data = txcmd_packet;
    CmdPacketTxInfo.timeStamp = OSAL_GetTickCount();
    CmdPacketTxInfo.cnt = 1;
    CmdPacketTxInfo.status = TX_STA_WAIT_ACK;

    ExtKds_LoadingDataToBeSent(CmdPacketTxInfo.data.buffer, CmdPacketTxInfo.data.len);
}

/**
  * @brief  串口接收回调
  * 
  * @return 
  */
static void ExtKds_Receivecb(VirtualHardware_enum_t dev, void *data, uint32_t len)//ok 
{
	uint32_t i = 0;
	uint8_t *p = (uint8_t *)data;

	/* 收到的数据写入缓存 */
	for (i = 0; i < len; i++)
	{
		OSAL_RingBufferWrite(CmdPacketRxInfo.rbHandle, p + i);
	}
}

static ErrorStatus ExtendKds_ProcessMbox(uint8_t *msg)
{
    Mc60UartMsg_t *temp = (Mc60UartMsg_t *)msg;
	uint16_t cmd = 0;//temp->cmd; //uint8_t


	uint16_t len = temp->len;
	mc60_send_cb_fun_t cb = temp->cb;// extkds_send_cb_fun_t
	uint8_t *data = temp->data;
	ErrorStatus res = ERROR;
	uint16_t sum_cal = 0;

    uart_txcmd_packet_stu_t *send_packer = NULL;
	ProtocolPacket_stu_t *sdata; // CmdPacket_stu_t
	
	EXTEND_KDS_LOG("temp->cmd:%04x\r\n",temp->cmd);
	if(temp->cmd == 0x0100) //0x0001
	{
		cmd = 0x01A0;
	}
	else if(temp->cmd == 0x0200) //0x0002
	{
		cmd = 0x02A0;
	}
	else if(temp->cmd == 0x0206) //0x0602
	{
		cmd = 0x0306;
	}
	else if(temp->cmd == 0x0300) //0x0003
	{
		cmd = 0x10A0; 
	}
	else if(temp->cmd == 0x0008) //0x0800
	{
		cmd = 0x0108;
	}
	else //0010
	{
		cmd = temp->cmd;
	}

		EXTEND_KDS_LOG("ExtendKds_ProcessMbox, cmd: %04x, len: %d, cb: %p\r\n", cmd, len, cb);
		//ExtKds_PrintfHexData("ExtKds Send Ack",temp->data, len);
		
		if (cb == NULL)//发送ACK
		{
			EXTEND_KDS_LOG("ExtKds_SendAck 001\r\n");
			res = ExtKds_SendAck(cmd,data,len); 
			goto exit;
		}
		EXTEND_KDS_LOG("ExtKds_SendAck 002\r\n");
		send_packer = (uart_txcmd_packet_stu_t *)OSAL_Malloc(sizeof(uart_txcmd_packet_stu_t));
		sdata = (ProtocolPacket_stu_t *)send_packer->buffer;
		sdata->head.stx = PROTOCOL_CMD_PACKET_STX;
		sdata->head.cmd = cmd; 
		sdata->head.reserved = 0xFF; 
		sdata->head.len = len;
		memcpy(sdata->dataBuf,data,len);
        sum_cal = ExtKds_CalcCheckSum(&sdata->head.cmd,sdata->head.len + 4);
		sdata->dataBuf[sdata->head.len] = (uint8_t)(sum_cal >> 8);
		sdata->dataBuf[sdata->head.len + 1] = (sum_cal & 0x00FF);
		sdata->dataBuf[sdata->head.len + 2] = PROTOCOL_CMD_PACKET_END;

		send_packer->len = sizeof(ProtocolPacket_stu_t) + len + 3;//
		send_packer->cb = cb;
		// if(cmd == 0xB0)//配网命令
		// {
		// 	send_packer->acktimeout = 60000;
		// 	OSAL_SetTaskStatus(TASK_STA_ACTIVE); //扩展模块流程开始：禁止系统休眠
		// }
		// else
		//{
			send_packer->acktimeout = PROTOCOL_RESEND_CMD_TIMEOUT;
		//}
		

		if (CmdPacketTxInfo.tbHandle != NULL)
		{
			if (OSAL_RingBufferWrite(CmdPacketTxInfo.tbHandle,send_packer) == SUCCESS)
			{
				res = SUCCESS;
			}  
		}
    
 exit:  
    if (send_packer) OSAL_Free(send_packer);
    return res; 
}

/**
  * @brief  UART任务函数
  *
  * @note   1.任务函数内不能写阻塞代码
  *         2.任务函数每次运行只处理一个事件
  *         
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t ExtKds_Task(uint32_t event)
{
	static uint8_t uart_init_flag;
	/* 系统启动事件 */
	if (event & EVENT_SYS_START)
	{
		if(uart_init_flag == 0)
		{
			/* 创建RX环形缓存 */
			CmdPacketRxInfo.rbHandle = OSAL_RingBufferCreate(EXTEND_KDS_RB_RXBUF_LENGTH, 1);
			/* 创建TX环形缓存 */
			CmdPacketTxInfo.tbHandle = OSAL_RingBufferCreate(5, sizeof(uart_txcmd_packet_stu_t));
			/* 注册串口接收回调 */
			Device_RegisteredCB(EXTEND_KDS_VHWL, ExtKds_Receivecb);
			/* 初始化UART协议层 */
			ExtKds_ProtocolInit();

			Device_ConfigCB(BLEWAKEMCU_VHWL, ENABLE);
			uart_init_flag = 1;
		}
		OSAL_EventRepeatCreate(COMP_MC60_UART, EVENT_EXTEND_KDS, EXTEND_KDS_EVT_PROC_CYCLE, EVT_PRIORITY_MEDIUM);
		EXTEND_KDS_LOG("ExtKds_Task start\r\n");
        Device_Enable(EXTEND_KDS_VHWL);
		return ( event ^ EVENT_SYS_START );
	}

	/* 串口处理事件 */
	if (event & EVENT_EXTEND_KDS)
	{
		ExtKds_ProtocolPro();
		ExtKds_ProcessTxQueue();
		return ( event ^ EVENT_EXTEND_KDS );
	}

	if (event & EVENT_EXTEND_KDS_SEND_ACK)//多个ACK包用到的
    {
        if (CmdPacketRxInfo.rx_msg) 
        {
            if (OSAL_MessagePublish(CmdPacketRxInfo.rx_msg, sizeof(Mc60UartMsg_t) + CmdPacketRxInfo.rx_msg->len) != SUCCESS)
            {
                EXTEND_KDS_LOG("OSAL_MessagePublish error\r\n");  
            }
        }
        return ( event ^ EVENT_EXTEND_KDS_SEND_ACK );   
    }

	if (event & EVENT_SYS_MBOX)
    {
        uint8_t buffer[MAX_PACKAGE_LEN + 10] = {0};
        while (OSAL_MboxAccept(buffer))
        {
            ExtendKds_ProcessMbox(buffer);
        }
        return ( event ^ EVENT_SYS_MBOX );
    }

	/* 系统休眠事件 */
	if (event & EVENT_SYS_SLEEP)
	{
        EXTEND_KDS_LOG("ExtKds_Task sleep\r\n");
		OSAL_EventDelete(COMP_MC60_UART, EVENT_EXTEND_KDS);
		Device_Disable(EXTEND_KDS_VHWL);
	    Device_Write(EXTEND_INT_VHWL, NULL, 0, 0);
		return ( event ^ EVENT_SYS_SLEEP );
    }
	return 0;
}
COMPONENT_TASK_EXPORT(COMP_MC60_UART, ExtKds_Task, 0); // COMP_EXTEND_KDS

/**
 * @brief  MC60唤醒MCU
 * @param
 * @return
 */
static int32_t MC60_WakeHandle(uint32_t dev)
{
    EXTEND_KDS_LOG("MC60_WakeHandle...\r\n");
    return 1;
}
COMPONENT_WAKEUP_EXPORT(COMP_MC60_UART, MC60_WakeHandle, BLEWAKEMCU_VHWL);

